home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / SampleSMSAMServer / SampleSMSAMServer.cp < prev    next >
Encoding:
Text File  |  1995-07-28  |  22.9 KB  |  942 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        SampleSMSAMServer.cp
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #ifndef __BLJSTANDARDINCLUDES__
  15. #include "BLJStandardIncludes.h"
  16. #endif
  17.  
  18. #ifndef __SAMPLESMSAMSERVER__
  19. #include "SampleSMSAMServer.h"
  20. #endif
  21.  
  22. #ifndef __FOLDERS__
  23. #include <Folders.h>
  24. #endif
  25.  
  26. #ifndef __GESTALTEQU__
  27. #include <GestaltEqu.h>
  28. #endif
  29.  
  30. #ifndef __MENUS__
  31. #include <Menus.h>
  32. #endif
  33.  
  34. #ifndef __WRITELINEWINDOW__
  35. #include "WriteLineWindow.h"
  36. #endif
  37.  
  38. #ifndef __DEBUGGINGGEAR__
  39. #include "DebuggingGear.h"
  40. #endif
  41.  
  42. #ifndef __DEBUGGINGMENUS__
  43. #include "DebuggingMenus.h"
  44. #endif
  45.  
  46. #ifndef __VIRTUALFILE__
  47. #include "VirtualFile.h"
  48. #endif
  49.  
  50. #ifndef __VIRTUALRAMORDISKFILE__
  51. #include "VirtualRamOrDiskFile.h"
  52. #endif
  53.  
  54. #ifndef __UTILITIES__
  55. #include "Utilities.h"
  56. #endif
  57.  
  58. #ifndef __TRANSCRIPTWINDOW__
  59. #include "TranscriptWindow.h"
  60. #endif
  61.  
  62. #ifndef __LOGWINDOW__
  63. #include "LogWindow.h"
  64. #endif
  65.  
  66. #ifndef __2020TOCONNECTORGATEWAY__
  67. // #include "2020toConnectorGateway.h"
  68. #endif
  69.  
  70. #ifndef __ATOBMAILGATEWAY__
  71. #include "AtoBMailGateway.h"
  72. #endif
  73.  
  74. #ifndef __2020HALFGATEWAY__
  75. #include "2020HalfGateway.h"
  76. #endif
  77.  
  78. #ifndef __HFSHALFGATEWAY__
  79. #include "HFSHalfGateway.h"
  80. #endif
  81.  
  82. #ifndef __CONNECTORHALFGATEWAY__
  83. // #include "ConnectorHalfGateway.h"
  84. #endif
  85.  
  86. // #ifndef __PAGERHALFGATEWAY__
  87. // #include "PagerHalfGateway.h"
  88. // #endif
  89.  
  90. #ifndef __CONNECTIONS__
  91. #include <Connections.h>
  92. #endif
  93.  
  94. #ifndef __COMMRESOURCES__
  95. #include <CommResources.h>
  96. #endif
  97.  
  98. #ifndef __FILETRANSFERS__
  99. #include <FileTransfers.h>
  100. #endif
  101.  
  102. #ifndef __UAPPLEEVENTS__
  103. #include "UAppleEvents.h"
  104. #endif
  105.  
  106. #ifndef __STATUSMONITOR__
  107. #include "StatusMonitor.h"
  108. #endif
  109.  
  110. #ifndef __STATUSDATABASE__
  111. #include "StatusDatabase.h"
  112. #endif
  113.  
  114. #ifndef __GATEWAYCONFIG__
  115. #include "GatewayConfig.h"
  116. #endif
  117.  
  118. #ifndef __LETTERLOG__
  119. #include "LetterLog.h"
  120. #endif
  121.  
  122. #ifndef    __BOVINECONSTANTS__
  123. #include "BovineConstants.h"
  124. #endif
  125.  
  126. #ifndef    __FONTS__
  127. #include <Fonts.h>
  128. #endif
  129.  
  130. #ifndef    __FILESPEC__
  131. #include "FileSpec.h"
  132. #endif
  133.  
  134. #ifndef __DEBUGGINGWINDOWS__
  135. #include "DebuggingWindows.h"
  136. #endif
  137.  
  138. #ifndef __STDIO__
  139. #include <stdio.h>
  140. #endif
  141.  
  142. #ifndef __STATUSWINDOW__
  143. #include "StatusWindow.h"
  144. #endif
  145.  
  146. #ifndef __EVENTTIMER__
  147. #include "EventTimer.h"
  148. #endif
  149.  
  150. #ifndef __THREADCLASSES__
  151. #include "ThreadClasses.h"
  152. #endif
  153.  
  154. /***********************************|****************************************/
  155.  
  156. //#define DefaultStackSize() *((long *)DefltStack)
  157. //#define StackBase()    *((Ptr *)CurStackBase)
  158.  
  159. Boolean gReadyToQuit;                //    this gets set to true when all of the threads have
  160. Boolean gPausing = false;            //    responded to the "we're quitting" flag
  161. Boolean gInBackground = false;        //    Assume we start execution in the foreground
  162.  
  163. TMailGateway* gMailGateway = nil;
  164. TStatusMonitor* gStatusMonitor = nil;
  165. Boolean gStartedThreads = false;
  166. short gBovineWorkingVRefNum, gBovineTempVRefNum;
  167. long gBovineWorkingDirID, gBovineTempDirID, gBovineLogDirID;
  168.  
  169. extern unsigned short gCurrentGatewayNumber;
  170. // extern void DebugDisposeCCLEngine();
  171. extern pascal void WWFlushOutputFile();
  172.  
  173. void CreateMainApplicationThread();
  174.  
  175. short                                 gBovineServerPrefsFile ;        //default initialization to zero
  176. short                                gApplicationFile ;                //default initialization to zero
  177. TStatusWindow *                     gStatusWindow = nil;
  178.  
  179. /***********************************|****************************************/
  180.  
  181. #define cAppleEventReply    40                // General command number used to process
  182. #define cFinderNew            41                // AppleEvent 'oapp'
  183. #define cFinderPrint         42                // AppleEvent 'pdoc'
  184. #define cFinderOpen            43                // AppleEvent 'odoc'
  185. #define cFinderQuit             44                // AppleEvent 'quit'
  186.  
  187. /***********************************|****************************************/
  188.  
  189. Boolean IsGatewayPausing ( )
  190. {
  191.     return gPausing;
  192. }
  193.  
  194. /***********************************|****************************************/
  195.  
  196. void SetGatewayPausing ( Boolean pause )
  197. {
  198.     if ( IsGatewayPausing ( ) )
  199.     {
  200.         gPausing = false;
  201.         if ( gStatusWindow )
  202.             gStatusWindow->SetButtonTitle ( 1, "\pPause");
  203.     }
  204.     else
  205.     {
  206.         gPausing = true;
  207.         if ( gStatusWindow )
  208.             gStatusWindow->SetButtonTitle ( 1, "\pResume");
  209.     }    
  210. }
  211.  
  212. /***********************************|****************************************/
  213.  
  214. void QuitGateway ( )
  215. {
  216.     gReadyToQuit = true;
  217. }
  218.  
  219. /***********************************|****************************************/
  220. /*pascal OSErr AppleEventsDispatch ( const AppleEvent& message, const AppleEvent& reply, long info )*/
  221.  
  222. pascal OSErr AppleEventsDispatch ( const AppleEvent* message, const AppleEvent* reply, long info )
  223. {
  224.     switch (info)
  225.     {
  226.         case cStatusLogInit:
  227.         case cItemsToBeMonitored:
  228.         case cStopMonitoring:
  229.         case cStatusSessionAlive:
  230.         case cMonitorCommand:
  231.         case cGetConfigCommand:
  232.         case cSetConfigCommand:
  233.             if ( gStatusMonitor )
  234.                 gStatusMonitor->HandleAppleEvents(*message, *reply, info);
  235.         break;
  236.  
  237.         case cFinderNew:
  238.         case cFinderOpen:    //    We don't open 'documents' per se, so ignore odocs and pdocs
  239.         case cFinderPrint:
  240.             break;
  241.  
  242.         case cFinderQuit:
  243.             gReadyToQuit = true;
  244.             break;
  245.             
  246.         default:
  247. #if debug
  248.             if (steveFlag.Flag(6))
  249.                 steve << "AppleEvent not handled by DispatchAppleEvent!! " << info << endl;
  250. #endif
  251.         break;
  252.     }
  253.  
  254.     return noErr;
  255. }
  256.  
  257. /***********************************|****************************************/
  258.  
  259. void HandleHighLevelEvent(EventRecord* event)
  260. {    extern T2020HalfGateway* g2020HalfGateway;
  261.  
  262.     OSErr theErr = noErr;
  263.     if ( g2020HalfGateway && g2020HalfGateway->HandleAppleMailHighLevelEvent ( *event ) )
  264.         ; //    An AOCE High Level event; so ignore it.
  265.     else
  266.         theErr = AEProcessAppleEvent(event);
  267.  
  268.     #if debug
  269.     if ( theErr == noErr )
  270.     {
  271.         return;
  272.     }
  273.     else if (theErr == errAEEventNotHandled)
  274.     {
  275.         if (steveFlag.Flag(6))
  276.             steve << "BovineServer::Did not handle the Apple Event - AEEventNotHandled" << endl;
  277.     }
  278.     else
  279.     {
  280.         if (steveFlag.Flag(6))
  281.             steve << "BovineServer::Error handling apple event :" << theErr << endl;
  282.     }
  283.     #endif
  284. }
  285.  
  286. /***********************************|****************************************/
  287.  
  288. void DoEvent(EventRecord*event)
  289. {
  290.     if ( TTranscriptWindow::IsLogWindowEvent ( *event ) )
  291.         return;
  292.         
  293.     if ( TLogWindow::IsLogWindowEvent ( *event ) )
  294.         return;
  295.         
  296. //    if (HandleDebuggingWindowsEvent(event))
  297. //        return;
  298.  
  299.     if ( HandleDebuggingMenuEvent ( event ) )
  300.         return;
  301.     
  302.     if ( TDialogWindow::HandleAnEvent ( *event ) )
  303.         return;
  304.         
  305.     // Figure out what type of event it is, and what to do about it
  306.     switch ( event->what )
  307.     {
  308.         case nullEvent:
  309.             break;
  310.  
  311.         case osEvt:
  312.             switch (event->message >> 24)
  313.             {
  314.                 case suspendResumeMessage:
  315.                     //    If we're resuming, then restore the cursor to the arrow
  316.                     gInBackground = ( (event->message & 0x01) != resumeFlag );
  317.                     if ( !gInBackground )
  318.                         InitCursor();
  319.                     break;
  320.             }
  321.             break;
  322.  
  323.         case kHighLevelEvent:
  324. #if debug
  325.             if (steveFlag.Flag(6))
  326.             {
  327.                 keith << "main: Incoming AppleEvent of type "; OutputOSType(keith, OSType(event->message));
  328.                 keith << " "; OutputOSType(keith, OSType(* (long *) &event->where)); keith << endl;
  329.             }
  330. #endif
  331.             HandleHighLevelEvent(event);
  332.             break;
  333.     }
  334. }
  335.  
  336. /***********************************|****************************************/
  337.  
  338. #pragma segment Main
  339. void SendLogToStatusMonitor(long tupleID, char* theMsg)
  340. {
  341.     if (gStatusMonitor != nil)
  342.     {
  343. #if debug
  344.         if (steveFlag.Flag(3))
  345.             steve << "Forcing update to status monitor!" << endl;
  346. #endif
  347.         gStatusMonitor->UpdateLog(tupleID, theMsg);
  348.     }
  349. }
  350.  
  351. /***********************************|****************************************/
  352.  
  353. #if debug
  354. #pragma segment MiscDebugOnly
  355. #endif
  356.  
  357. Boolean GetAutostartOption()
  358. {
  359.     FInfo finderInfo;
  360.     return HGetFInfo(gBovineWorkingVRefNum, gBovineWorkingDirID, k2020ServerAutoStartFile, &finderInfo) == noErr;
  361. }
  362.  
  363. /***********************************|****************************************/
  364.  
  365. void
  366. ToggleAutostartOption()
  367. {
  368.     if ( GetAutostartOption() )
  369.         HDelete(gBovineWorkingVRefNum, gBovineWorkingDirID, k2020ServerAutoStartFile);
  370.     else
  371.         HCreate(gBovineWorkingVRefNum, gBovineWorkingDirID, k2020ServerAutoStartFile,'\?\?\?\?', '\?\?\?\?');
  372. }
  373.  
  374. /***********************************|****************************************/
  375.  
  376. void
  377. SetNewGlobalGateway ( TMailGateway* newGateway, const char* serverName = nil )
  378. {
  379.     delete gMailGateway;
  380.     gMailGateway = newGateway;
  381.  
  382.     //    Set up the status monitor.
  383.     gStatusMonitor = new TStatusMonitor ( gMailGateway );
  384.     if (gStatusMonitor)
  385.         gStatusMonitor->Run();
  386.  
  387.     if ( !gMailGateway )
  388.         return;
  389.     else if ( !serverName )
  390.         return;
  391.     else if ( gMailGateway->Setup ( gBovineWorkingVRefNum, gBovineWorkingDirID, serverName ) )
  392.         gMailGateway->Run ();
  393.     else
  394.         SetNewGlobalGateway ( nil );
  395.  
  396.  
  397.     keith << "main: " << serverName << ".Setup()" << endl;
  398. }
  399.  
  400. /***********************************|****************************************/
  401.  
  402. Boolean gMailGatewayShuttingDown = false;
  403.  
  404. /***********************************|****************************************/
  405.  
  406. Boolean ShutDownGateway ( )
  407. {
  408.     Boolean result = false;
  409.     
  410.     if ( gMailGateway )
  411.     {
  412.         keithDB ( "BovineServer::ShutDownGateway(), beginning shutdown process." );
  413.         gMailGatewayShuttingDown = true;
  414.         result = gMailGateway->PrepareToShutDown ( 60 );
  415.     }
  416.     
  417.     return result;
  418. }
  419.  
  420. /***********************************|****************************************/
  421.  
  422. void
  423. SetupAtoBGateway ( THalfGateway* a, THalfGateway* b, const char* serverName )
  424. {
  425.     SetNewGlobalGateway ( new TAtoBMailGateway ( a, b, gBovineWorkingVRefNum, gBovineWorkingDirID ), serverName );
  426. }
  427.  
  428. /***********************************|****************************************/
  429.  
  430. void
  431. CreateMailGatewayNWrapper(unsigned long gatewayToCreate, unsigned long )
  432. {
  433.     switch (gatewayToCreate)
  434.     {
  435.         case k2020ConnectorItem:
  436.         break;
  437.  
  438.         case k2020HFSItem:
  439.             SetupAtoBGateway ( new T2020HalfGateway, new THFSHalfGateway, "2020∞HFSMailA" );
  440.         break;
  441.  
  442.         case kHFSConnectorItem:
  443.         break;
  444.  
  445.         case kATSHFSItem:
  446.             SysBeep ( 10 );
  447.         break;
  448.  
  449.         case kHFSPagerItem:
  450.         break;
  451.  
  452.         case kHFSHFSItem:
  453.             SetupAtoBGateway ( new THFSHalfGateway, new THFSHalfGateway, "HFSMailA∞HFSMailB" );
  454.         break;
  455.  
  456.         default:
  457.             SetNewGlobalGateway ( nil );
  458.         break;
  459.     }
  460.  
  461.     gCurrentGatewayNumber = gMailGateway ? (unsigned short) gatewayToCreate : 0;
  462. }
  463.  
  464. /***********************************|****************************************/
  465.  
  466. void CreateMailGatewayN(short n)
  467. {
  468. //     CreateMailGatewayNWrapper ( n, 0 );
  469.     createThread('STAR', (FNULUL) CreateMailGatewayNWrapper, 32 * 1024, n, 0, TNormalMode );
  470. }
  471.  
  472. /***********************************|****************************************/
  473.  
  474. //
  475. //    This function will try to kill the thread manager and then exit from the application.
  476. //    It is designed to be used from Macsbug, by typing g exitApp
  477. //
  478.  
  479. #pragma segment Main
  480. extern "C"
  481. {
  482.     void exitApp ()
  483.     {
  484.         SetA5( *(long*) LMGetCurrentA5() );
  485.         WWFlushOutputFile();
  486.  
  487.         ///    Try to kill the thread manager.  With luck, it'll work.
  488.         if (gStartedThreads)
  489.         {
  490.             #ifndef newThreads
  491.             endThreadMgr();
  492.             #endif
  493.             
  494.             gStartedThreads = false;
  495.         }
  496.  
  497.         ExitToShell();
  498.     }
  499. }
  500.  
  501. /***********************************|****************************************/
  502.  
  503. void PauseIfDiskSpaceIsLow()
  504. {
  505.     const unsigned long kLowLimit = 2097152; // At least 2 Meg
  506.     const unsigned long kOneMeg = 1048576; // At least 2 Meg
  507.  
  508.     Str31 volName;
  509.     short vRefNum;
  510.     long freeBytes;
  511.     short drvNum = -1;
  512.     OSErr err = GetVInfo (drvNum,(StringPtr) &volName, &vRefNum,&freeBytes);
  513.  
  514.     if ( (err == noErr) && (freeBytes < kLowLimit))
  515.     {
  516.         if ( ! IsGatewayPausing () ) {
  517.             steve << date << " " << time << "Pausing gateway because '" << volName << "' is low on free space." << endl;
  518.             SetGatewayPausing ( true );
  519.         }
  520.     }
  521. }
  522.  
  523. /***********************************|****************************************/
  524.  
  525. #pragma segment Main
  526.  
  527. Boolean CheckMemoryStatus (Boolean onlyPrintIfChanged = true, Boolean verbose = false, Boolean forcePurge = false)
  528. {
  529.     long growSize;
  530.     long freeMem = FreeMem();
  531.     long largestBlock = MaxMem(&growSize);
  532.     Boolean result = false;
  533.     static long gCheckMemoryStatusSavedFreeMemAmount = 0;
  534.  
  535.     if (((onlyPrintIfChanged == false) || (gCheckMemoryStatusSavedFreeMemAmount != freeMem)) &&
  536.         (verbose || (freeMem <= 65536) || (largestBlock < 32768)))
  537.     {
  538.         keith << time << "Free memory:" << freeMem << " ";
  539.  
  540.         if (forcePurge)
  541.         {
  542.             PurgeMem(maxSize);
  543.             keith << "(" << FreeMem() << "after purge) ";
  544.         }
  545.  
  546.         largestBlock = MaxMem(&growSize);
  547.         keith << " LargestBlock:" << largestBlock << endl;
  548.         result = true;
  549.     }
  550.  
  551.     return result;
  552. }
  553.  
  554. /***********************************|****************************************/
  555.  
  556. unsigned long GetDateTimeF ( )
  557. {
  558.     unsigned long result;
  559.     GetDateTime ( & result );
  560.     
  561.     return result;
  562. }
  563.  
  564. /***********************************|****************************************/
  565.  
  566. unsigned long gGatewayLoadIndicator [ 16 ] =  { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
  567.  
  568. /***********************************|****************************************/
  569.  
  570. Boolean ThreadWaitNextEvent ( short eventMask, EventRecord* event, RgnHandle mouseRgn )
  571. {
  572.     TEventTimer timeOurThreadsAreTaking, timeOurThreadsPlusWaitNextEventTakes;
  573.     Boolean result = false;
  574.         
  575.     EventAvail ( eventMask, event );
  576.     if ( event->what == nullEvent )
  577.     {
  578.         TThreadManagerThread::WakeUpSleepingThreadsTask ();
  579.         
  580.         timeOurThreadsAreTaking.Start();
  581.         timeOurThreadsPlusWaitNextEventTakes.Start();
  582.         
  583.         //    Now, let all of our threads run.
  584.         TThread::YieldCurrentThread ();
  585.         
  586.         timeOurThreadsAreTaking.Stop ();
  587.         
  588.         unsigned long timeToSleep = 15;
  589.         result = WaitNextEvent ( eventMask, event, timeToSleep, mouseRgn );
  590.     
  591.         timeOurThreadsPlusWaitNextEventTakes.Stop();
  592.     
  593.         //    Now, store the time we consumed in the array indicators.  This is a 16 second, revolving    
  594.         //    array of how many microseconds we used during the previous 16 seconds of real time.
  595.         unsigned long seconds = ( GetDateTimeF () & 0x0000000f );
  596.         gGatewayLoadIndicator[ seconds ] += timeOurThreadsAreTaking.GetElapsedTimeInMicroseconds ();
  597.         gGatewayLoadIndicator[ ( seconds + 1 ) & 0x0000000f ] = 0;
  598.         
  599.         #if 0
  600.         short percentOfTimeConsumedByUs = ( ( 100 * timeOurThreadsAreTaking.GetElapsedTimeInMicroseconds() ) / timeOurThreadsPlusWaitNextEventTakes.GetElapsedTimeInMicroseconds () );
  601.         
  602.         keith << "ThreadWaitNextEvent::load=";
  603.         keith << GetCurrentServerLoad() << " % we used = " << percentOfTimeConsumedByUs << "% "  <<
  604.                         timeOurThreadsAreTaking.GetElapsedTimeInMicroseconds() << " of " <<
  605.                         timeOurThreadsPlusWaitNextEventTakes.GetElapsedTimeInMicroseconds() << endl;
  606.                         
  607.         #endif
  608.     }
  609.     else
  610.     {
  611.         unsigned long timeToSleep = 15;
  612.         result = WaitNextEvent ( eventMask, event, timeToSleep, mouseRgn );
  613.     }
  614.     
  615.     return result;
  616. }
  617.  
  618. /***********************************|****************************************/
  619.  
  620. unsigned long GetCurrentServerLoad ( )
  621. {
  622.     unsigned long result = 0;
  623.     for ( unsigned long i = 0; i < 16; i ++ )
  624.         result += gGatewayLoadIndicator [ i ];
  625.     result = between ( result / ( 16 * 10000 ), 0, 100 ); //    make it into a percent used
  626.     
  627.     return result;
  628. }
  629.  
  630. /***********************************|****************************************/
  631.  
  632. #pragma segment Initialize
  633.  
  634. void SetUpVirtualFiles ()
  635. {
  636.     // Create Bovine Temp folder.  Temporary items are kept in this folder.
  637.     gBovineTempDirID = CreateFolderIfItDoesntExist(gBovineWorkingVRefNum, gBovineWorkingDirID, "\pBovineTemp");
  638.     DeleteFilesInFolder(gBovineTempVRefNum, gBovineTempDirID);
  639.  
  640.     FSSpec spec;
  641.     spec.vRefNum = gBovineWorkingVRefNum;
  642.     spec.parID = gBovineTempDirID;
  643.     TVirtualRamOrDiskFile::SetDefaultStorageLocation (spec);
  644.  
  645.     // Create Bovine Logs
  646.     gBovineLogDirID = CreateFolderIfItDoesntExist(gBovineWorkingVRefNum, gBovineWorkingDirID, "\pBovine Logs");
  647.     gBovineLetterLog = new TLetterLog ( TFileSpec ( gBovineWorkingVRefNum, gBovineLogDirID, "\pLetterLog" ) );
  648.     gBovineLetterLog->Open ();
  649. }
  650.  
  651. /***********************************|****************************************/
  652.  
  653. short OpenApplicationPreferencesFile ( )
  654. {
  655.     //    The preferences file should be called "<Application Name> Prefs".
  656. /*    CStr255 prefsFileName = * (StringPtr) 0x910 + "\p Prefs";*/
  657.     Str255 prefsFileName = * (StringPtr) 0x910 + "\p Prefs";
  658.     short result = -1;
  659.     
  660.     short prefsVRefNum;
  661.     long prefsDirID;
  662.     
  663. /*  first-time escapade, get refnum for application if we don't have it already  */
  664.  
  665.     if ( !gApplicationFile && !gBovineServerPrefsFile )
  666.         gApplicationFile = CurResFile();
  667.         
  668.     if ( FindFolder ( kOnSystemDisk, kPreferencesFolderType, kCreateFolder, & prefsVRefNum, & prefsDirID) == noErr ) {
  669.         HCreate ( prefsVRefNum, prefsDirID, prefsFileName, 'BLoJ', 'pref' );
  670.         HCreateResFile ( prefsVRefNum, prefsDirID, prefsFileName );
  671.         result = HOpenResFile ( prefsVRefNum, prefsDirID, prefsFileName, fsRdWrPerm );
  672.         if ( result > 0 ) 
  673.         {
  674.             UseResFile ( result );  //make it the current resource file if it was already open
  675.         }
  676.     }
  677.     
  678.     return result;
  679. }
  680.  
  681. /***********************************|****************************************/
  682.  
  683. #pragma segment Initialize
  684. extern Boolean gBovineServerWasInitialized;
  685. extern void SetNewHandler ();
  686.  
  687. #include <New.h>
  688.  
  689. void BreakStr ( const Str255 str );
  690.  
  691. void InitializeApp()
  692. {
  693.     SetApplLimit((Ptr) ((long) LMGetCurStackBase() - min(LMGetDefltStack(), 0x4000)));
  694.     MaxApplZone(); /* expand the heap so code segments load at the top */
  695.  
  696.     for ( short moreMastersIndex = 40; moreMastersIndex >= 0; moreMastersIndex-- )
  697.         MoreMasters();
  698.  
  699.     InitGraf(&qd.thePort);
  700.     InitFonts();
  701.     InitWindows();
  702.     InitMenus();
  703.     TEInit();
  704.     InitDialogs(nil);
  705.     InitCursor();
  706.     
  707.     // Get current directory and volume
  708.     WDPBRec paramBlock;
  709.     paramBlock.ioNamePtr = nil;
  710.     OSErr err = PBHGetVol(¶mBlock,false);
  711.     long dRefNum = paramBlock.ioWDDirID;
  712.     gBovineWorkingVRefNum = gBovineTempVRefNum = paramBlock.ioWDVRefNum;
  713.     
  714.     //  Set res file reference of the application file
  715.     //        gApplicationFile = CurResFile();  now done in OpenApplicationPreferencesFile()
  716.  
  717.     //    Create the Bovine Working directory, which will form the 'top' of a tree below which
  718.     //    all of the different gateway and half gateway modules will use to store configuration
  719.     //    information, data files, etc.
  720.     //
  721.     gBovineWorkingDirID = CreateFolderIfItDoesntExist(gBovineWorkingVRefNum, dRefNum, "\pBovine Working");
  722.     
  723.     //    Open up the preferences file, creating one if it does not already exist.
  724.     //  This is normally done as part of DebugFlag init
  725.     if ( gBovineServerPrefsFile == 0 )
  726.         gBovineServerPrefsFile = OpenApplicationPreferencesFile();
  727.     
  728.     SetNewHandler();
  729.  
  730.     #ifndef newThreads
  731.     initThreadMgr (true);
  732.     #else
  733.     //    Verify that the threads manager is installed.
  734.     long value;
  735.     if ( ( Gestalt ( gestaltThreadMgrAttr, &value ) != noErr ) || ( value & ( 1 << gestaltThreadMgrPresent) == 0 ) )
  736.     {
  737.         #if debug
  738.         DebugStr ("\p The Threads Manager extension must be installed to use this gateway." );
  739.         #endif 
  740.     
  741.         ExitToShell();
  742.     }
  743.     
  744.     CreateMainApplicationThread();
  745.     #endif
  746.     
  747.     gReadyToQuit = false;
  748.     SetGatewayPausing ( false );
  749.     gStartedThreads = true;
  750.  
  751.     #ifndef newThreads
  752.     TSetRefCon('MAIN');
  753.     TSetWNESleep(24);
  754.     #endif
  755.     
  756.     InitializeDebuggingWindows();
  757.     void                        ShowThreadStatusDialog ( );
  758.  //    ShowThreadStatusDialog();
  759.      
  760.     gBovineServerWasInitialized = true;
  761.  
  762.     addressTypesFlag.SetFlag ( 1 );
  763.     addressTypesFlag.SetFlag ( 2 );
  764.     addressTypesFlag.SetFlag ( 3 );
  765.     addressTypesFlag.SetFlag ( 4 );
  766.     addressTypesFlag.SetFlag ( 8 );
  767.     addressTypesFlag.SetFlag ( 9 );
  768.     addressTypesFlag.SetFlag ( 10 );
  769.     addressTypesFlag.SetFlag ( 11 );
  770.     addressTypesFlag.SetFlag ( 12 );
  771.     addressTypesFlag.SetFlag ( 13 );
  772.  
  773.     //    Set up the debugging environment...
  774.     InitializeDebuggingMenus();
  775.  
  776.     //    Initialize the various communications toolbox routines.
  777.     {    
  778.         OSErr    err = InitCRM();
  779.         if (err)
  780.             keith << "main: InitCRM() returned " << err << endl;
  781.             
  782.         err = InitCM();
  783.         if (err )
  784.             keith << "main: InitCM() returned " << err << endl;
  785.         err = InitFT();
  786.         if (err)
  787.             keith << "main: InitFT() returned " << err << endl;
  788.     }
  789.  
  790.  
  791.     //    If we don't have enough heap space or memory, complain
  792.     {    long available = (long) GetApplLimit() - (long) ApplicZone();
  793.  
  794.         if ( available < kMinHeap )
  795.         {
  796.             Str255    buffer;
  797.             sprintf ((char *) &buffer[0], "*** BovineServer needs %d bytes in the heap -- only %d are available.", kMinHeap, available);
  798.  
  799.             buffer[0] = strlen((char *) &buffer[0]);
  800.             BreakStr (buffer);
  801.         }
  802.     }
  803.  
  804.     InitUAppleEvents((ProcPtr) &AppleEventsDispatch);
  805.  
  806.     {
  807.         long total, contig;
  808.         PurgeSpace(&total, &contig);
  809.         if (total < kMinSpace)
  810.         {
  811.             Str255    buffer;
  812.             sprintf ((char *) &buffer[0], "*** BovineServer needs %d bytes in the memory -- only %d are available.",
  813.                                 kMinSpace, total);
  814.             buffer[0] = strlen((char *) &buffer[0]);
  815.             BreakStr (buffer);
  816.         }
  817.     }
  818.  
  819.     gStatusWindow = new TStatusWindow ( 2000, 2000, & GetCurrentServerLoad );
  820.     gStatusWindow->ShowWindow ();
  821.     
  822.     SetUpVirtualFiles ();
  823.  
  824. #if debug
  825.     if (GetAutostartOption())
  826.     {
  827.         keith << "Startup: Autostart option active, instantiating default gateway." << endl;
  828.         CreateMailGatewayN(1);
  829.         gCurrentGatewayNumber = gMailGateway ? 1 : 0;
  830.         SetGatewayPausing ( false );
  831.     }
  832. #else
  833.     CreateMailGatewayN(1);
  834.     gCurrentGatewayNumber = gMailGateway ? 1 : 0;
  835. #endif
  836. }
  837.  
  838. /***********************************|****************************************/
  839.  
  840. #pragma segment Main
  841.  
  842. #ifdef newThreads
  843. Boolean TWaitNextEvent ( long eventMask, EventRecord* eventRecord, RgnHandle rgn )
  844. {
  845.     TYield();
  846.     return WaitNextEvent ( eventMask, eventRecord, (gInBackground) ? 30 : 5, rgn );
  847. }
  848. #endif
  849.  
  850. int main ()
  851. {
  852.     //    Hold down the mouse button to skip execution of the program
  853.     if (Button())
  854.         exitApp();
  855.  
  856.     InitializeApp();                /* initialize the program */
  857. //    UnloadSeg( _DataInit);            /* note that _DataInit must not be in Main! */
  858. //    UnloadSeg((Ptr) Initialize);    /* note that Initialize must not be in Main! */
  859.  
  860.     EventRecord event;
  861.  
  862.     do
  863.     {
  864.         //    Update the 'time' in the gateway status window.
  865.         if ( gStatusWindow )
  866.         {
  867.             Str255 timeString;
  868.             unsigned long currentTime;
  869.             static unsigned long gStatusWindowTimeLastUpdate = 0;
  870.             
  871.             GetDateTime ( & currentTime );
  872.             
  873.             if ( currentTime != gStatusWindowTimeLastUpdate )
  874.             {
  875.                 IUTimeString ( currentTime, true, timeString );        
  876.                 gStatusWindow->SetTextItem ( 5, timeString );
  877.                 gStatusWindowTimeLastUpdate = currentTime;
  878.             }
  879.         }
  880.         
  881.         if ( IsGatewayPausing () )
  882.         {
  883.             if (WaitNextEvent (everyEvent, &event, 5, nil) )
  884.                 DoEvent (&event);
  885.         }
  886.         else if ( ThreadWaitNextEvent (everyEvent, &event, nil) )
  887.             DoEvent (&event);
  888.         else
  889.             TDialogWindow::HandleAnEvent ( event );
  890.  
  891.         if ( gStatusWindow )
  892.             gStatusWindow->UpdateLoadIndicator ();
  893.  
  894.         FlushDebugBuffers ();
  895.         
  896.         CheckMemoryStatus(true, false, false);
  897.         PauseIfDiskSpaceIsLow();
  898.  
  899.         //    If the gateway is in the process of 'shutting down', then
  900.         //    check whether it has finished.  If so, then quit.        
  901.         if ( gMailGatewayShuttingDown )
  902.             if ( gMailGateway && gMailGateway->ReadyToShutDown ( ) )
  903.             {
  904.                 gReadyToQuit = gMailGateway->ShutDown ();
  905.  
  906.                 keith << "main:: After shutdown, thread status is:" << endl;
  907.                 extern void ShowAllThreadStatus ( ostream& );
  908.                 ShowAllThreadStatus( keith );
  909.             }
  910.     }
  911.     while ( !gReadyToQuit );
  912.  
  913.     keith << "main: Quitting…, gReadyToQuit = true" << endl << flush;
  914.  
  915. #if debug
  916.     // DebugDisposeCCLEngine();
  917. #endif
  918.  
  919.     delete gMailGateway;
  920.     delete gBovineLetterLog;
  921.  
  922.     keith << "Quitting gateway! " << time << endl << flush;
  923.     #ifndef newThreads
  924.     endThreadMgr();
  925.     #endif
  926.     
  927.     FlushDebugBuffers ();
  928.  
  929.     unsigned long stopTime = (unsigned long) TickCount () + 90;
  930.     while ( TickCount() < stopTime )  ;
  931.  
  932.     void HideThreadStatusDialog ();
  933.     HideThreadStatusDialog ();
  934.         
  935.     CloseResFile ( gBovineServerPrefsFile );
  936.     gBovineServerPrefsFile = -1;
  937.     
  938.     return noErr;
  939. }
  940.  
  941.  
  942.